local jass = require 'jass.common'
local japi = require 'jass.japi'
local runtime = require 'jass.runtime'
local dbg = require 'jass.debug'
local slk = require 'jass.slk'

--[[
    不可叠加 默认生效最后添加的武器
]]

local attacker = {
    __tostring = function(self) 
        return ('attacker[%s]'):format(self.handle or 0) 
    end,
    __call = function(self, data) 
        for k,v in pairs(data) do 
            self[k] = v 
        end 
        return self 
    end,
} 
setmetatable(attacker,attacker)

-- 获得时 on_add 

-- 出手时 on_attack

-- 删除时 on_remove

local mt = { }
attacker.__index = mt 

-- 结构
mt.type = 'attacker'

-- 武器优先级 (类似于法球不可叠加 取优先级最高的 如果优先级相同则根据 优先生效后添加的)
mt.level = 1

-- 武器名称
mt.name = nil 

-- 所有者
mt.owner = nil 

--禁用计数
mt.enable_count = 0

-- 武器音效
mt.weapon = nil

-- 屏蔽原始武器
mt.cover_flag = true

function mt:get_id()
    return self.name 
end 

-- 执行事件
function mt:notify(name,...)
    local func = self[name]
    if func then 
        return select(2, xpcall(func, runtime.error_handle, self, ...))
    end 
end 

function mt:attack(target)
    self:notify("on_attack", target)
end 

function mt:damage(target)
    if self:notify("on_damage", target) ~= false then 
        self:notify("on_orb", target)
    end
end 

local function is_enable(self)
	return self.enable_count == 0
end

local function enable(self)
    local unit = self.owner
	self.enable_count = self.enable_count - 1
	if not self.removed and self.added and self.enable_count == 0 and not self.has_on_add then
		self.has_on_add = true
        if self.cover_flag then 
            self.old_attacker = japi.GetUnitState(unit.handle , 0x58)
            self.old_sound = japi.GetUnitState(unit.handle , 0x22)
            self.old_missile = unit:get_slk('Missileart','.mdx')
            japi.SetUnitState(unit.handle , 0x22, 0)
            japi.SetUnitState(unit.handle , 0x58, 4)
            japi.SetUnitMissileModel(unit.handle,'.mdx')
        end
        unit.attacker = self
		self:notify('on_add')
	end
end

local function disable(self)
    local unit = self.owner
	self.enable_count = self.enable_count + 1
	if not self.removed and self.added and self.enable_count == 1 and self.has_on_add then
		self.has_on_add = nil
        if self.cover_flag then 
            japi.SetUnitState(unit.handle , 0x58, self.old_attacker)
            japi.SetUnitState(unit.handle , 0x22, self.old_sound)
            japi.SetUnitMissileModel(unit.handle, self.old_missile )
        end
		self:notify('on_remove')
	end
end

-- 删除武器
function mt:remove()
    if self.removed then  
        return  
    end 

    self.removed = true
    local unit = self.owner 
    local list = unit.attackers_list

    for i=#list,1,-1 do 
        if self == list[i] then 
            table.remove(list,i)
            break
        end 
    end 

    -- 不是被禁用的buff会触发on_remove
	if is_enable(self) and self.added and self.has_on_add then 
		self.added = nil 
		self.has_on_add = nil 
        if self.cover_flag then 
            japi.SetUnitState(unit.handle , 0x58, self.old_attacker)
            japi.SetUnitState(unit.handle , 0x22, self.old_sound)
            japi.SetUnitMissileModel(unit.handle, self.old_missile )
        end 
        unit.attacker = nil
		self:notify('on_remove')
        if list[1] then
            enable(list[1])
        end
	end

    unit.attackers[self] = nil 
end 

-- 初始化武器
function mt:add()
	if self.added or self.removed then 
		return false
	end 
    self.added = true 

    local unit = self.owner 
    
    --武器表
    if not unit.attackers then 
        unit.attackers = {}
    end
    -- 武器优先级表
    if not unit.attackers_list then 
        unit.attackers_list = {}
    end 

    local list = unit.attackers_list
    for i = 1,#list +1 do 
        local this = list[i]
        if not this then 
            table.insert(list, i, self)
            if i > 1 then 
                disable(self)
            end 
            break
        end 
        if this.level < self.level then 
            table.insert(list, i, self)
            if i == 1 then 
                disable(this)
            else
                disable(self)
            end 
            break
        end 
    end 
    
	if is_enable(self) then 
		if not self.has_on_add then
			self.has_on_add = true
            if self.cover_flag then 
                self.old_attacker = japi.GetUnitState(unit.handle , 0x58)
                self.old_sound = japi.GetUnitState(unit.handle , 0x22)
                self.old_missile = unit:get_slk('Missileart','.mdx')
                japi.SetUnitState(unit.handle , 0x58, 4.0)
                japi.SetUnitState(unit.handle , 0x22, 0)
                japi.SetUnitMissileModel(unit.handle,'.mdx')
            end
			self:notify('on_add')
            unit.attacker = self
		end 
		if self.removed then
			return
		end
	end 

    unit.attackers[self] = true

    return self
end 

local gchash = 0

-- 添加武器
function ac.unit.__index:add_attacker(name, info)
    local data = ac.attacker[name] 
    if not data then 
        log.error('没有配置武器',name)
        return 
    end  
    local weapon = setmetatable({ }, data.mt)
    if info then 
        for k,v in pairs(info) do 
            weapon[k] = v 
        end 
    end 
    weapon.name = name 
    weapon.owner = self
    gchash = gchash + 1 
    weapon.gchash = gchash
    dbg.gchash(weapon, gchash)
    weapon:add() 
    return weapon
end 

-- 移除所有武器
function ac.unit.__index:remove_attackers()
    for atk in pairs(self.attackers) do 
        atk:remove()
    end 
end 

ac.attacker = { } 
setmetatable(ac.attacker,{
    __index = attacker,
    __call = function(self, name)
        local mt = {}
        mt.name = name
        mt.mt = {
            __tostring = attacker.__tostring,
            __index = mt,
        } 
        setmetatable(mt,attacker)
        self[name] = mt
        return mt 
    end,
}) 

return attacker